"""
基于Airtest的移动端驱动器
支持Android和iOS设备的自动化操作
"""

import time
import logging
import os
from typing import Optional, Tuple, Dict, Any
from utils.mobile_driver_base import MobileDriverBase

try:
    from airtest.core.api import (
        connect_device,
        start_app,
        stop_app,
        touch,
        exists,
        wait,
        swipe,
        keyevent,
        snapshot,
        sleep,
        Template,
        text as airtest_text,
    )
    from airtest.core.android.adb import ADB
    from airtest.core.settings import Settings as ST

    AIRTEST_AVAILABLE = True
except ImportError as e:
    print(f"Airtest导入失败: {e}")
    AIRTEST_AVAILABLE = False

    # 创建占位符类
    class ST:
        THRESHOLD_STRICT = 0.7
        THRESHOLD = 0.8
        OPDELAY = 1
        FIND_TIMEOUT = 5

    def connect_device(*args, **kwargs):
        raise ImportError("Airtest未安装")

    def start_app(*args, **kwargs):
        raise ImportError("Airtest未安装")

    def stop_app(*args, **kwargs):
        raise ImportError("Airtest未安装")

    def touch(*args, **kwargs):
        raise ImportError("Airtest未安装")

    def exists(*args, **kwargs):
        return False

    def wait(*args, **kwargs):
        return None

    def swipe(*args, **kwargs):
        raise ImportError("Airtest未安装")

    def keyevent(*args, **kwargs):
        raise ImportError("Airtest未安装")

    def snapshot(*args, **kwargs):
        raise ImportError("Airtest未安装")

    def sleep(*args, **kwargs):
        time.sleep(args[0] if args else 1)

    def airtest_text(*args, **kwargs):
        raise ImportError("Airtest未安装")

    class Template:
        def __init__(self, *args, **kwargs):
            raise ImportError("Airtest未安装")

    class ADB:
        def __init__(self):
            raise ImportError("Airtest未安装")


class AirtestMobileDriver(MobileDriverBase):
    """基于Airtest的移动端驱动器"""

    def __init__(self, config: dict):
        self.config = config
        self.device = None
        self.logger = self._setup_logger()

        # 配置Airtest设置
        ST.THRESHOLD_STRICT = 0.7  # 图像识别严格模式阈值
        ST.THRESHOLD = 0.8  # 图像识别阈值
        ST.OPDELAY = 1  # 操作延迟
        ST.FIND_TIMEOUT = 5  # 查找元素超时时间

    def _setup_logger(self) -> logging.Logger:
        """设置日志记录器"""
        logger = logging.getLogger("AirtestMobileDriver")
        if not logger.handlers:
            handler = logging.StreamHandler()
            formatter = logging.Formatter(
                "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
            )
            handler.setFormatter(formatter)
            logger.addHandler(handler)
            logger.setLevel(logging.INFO)
        return logger

    def init_device(self) -> None:
        """初始化移动设备连接"""
        try:
            # 获取设备ID
            device_id = self.config.get("mobile", {}).get("device_id", "auto")

            if device_id == "auto":
                # 自动连接第一个可用设备
                adb = ADB()
                devices = adb.devices()
                if not devices:
                    raise RuntimeError("未检测到任何Android设备")
                device_id = devices[0][0]

            # 连接Android设备
            device_uri = f"Android:///{device_id}"
            self.device = connect_device(device_uri)

            self.logger.info(f"已连接到设备: {device_id}")

            # 获取设备信息
            if hasattr(self.device, "get_display_info"):
                display_info = self.device.get_display_info()
                self.logger.info(f"设备分辨率: {display_info}")

        except Exception as e:
            self.logger.error(f"设备连接失败: {e}")
            raise

    def start_app(self, package_name: Optional[str] = None) -> bool:
        """启动App"""
        try:
            if package_name is None:
                package_name = self.config.get("mobile", {}).get(
                    "app_package", "cn.damai"
                )

            self.logger.info(f"正在启动App: {package_name}")
            start_app(package_name)
            sleep(3)  # 等待App启动
            return True

        except Exception as e:
            self.logger.error(f"启动App失败: {e}")
            return False

    def stop_app(self, package_name: Optional[str] = None) -> bool:
        """停止App"""
        try:
            if package_name is None:
                package_name = self.config.get("mobile", {}).get(
                    "app_package", "cn.damai"
                )

            self.logger.info(f"正在停止App: {package_name}")
            stop_app(package_name)
            sleep(1)
            return True

        except Exception as e:
            self.logger.error(f"停止App失败: {e}")
            return False

    def click_coordinate(self, x: int, y: int) -> bool:
        """点击坐标"""
        try:
            touch((x, y))
            return True
        except Exception as e:
            self.logger.error(f"点击坐标失败: {e}")
            return False

    def click_text(self, text: str, timeout: int = 5) -> bool:
        """点击包含指定文本的元素"""
        try:
            # 使用Airtest的文本查找功能
            if exists(airtest_text(text)):
                touch(airtest_text(text))
                return True
            else:
                self.logger.warning(f"未找到文本: {text}")
                return False
        except Exception as e:
            self.logger.error(f"点击文本失败: {e}")
            return False

    def click_image(self, image_path: str, timeout: int = 5) -> bool:
        """通过图像识别点击元素"""
        try:
            template = Template(image_path, threshold=0.7)
            if exists(template):
                touch(template)
                return True
            else:
                self.logger.warning(f"未找到图像: {image_path}")
                return False
        except Exception as e:
            self.logger.error(f"图像点击失败: {e}")
            return False

    def wait_for_text(self, text: str, timeout: int = 10) -> bool:
        """等待文本出现"""
        try:
            result = wait(airtest_text(text), timeout=timeout)
            return result is not None
        except Exception as e:
            self.logger.error(f"等待文本失败: {e}")
            return False

    def wait_for_image(self, image_path: str, timeout: int = 10) -> bool:
        """等待图像出现"""
        try:
            template = Template(image_path, threshold=0.7)
            result = wait(template, timeout=timeout)
            return result is not None
        except Exception as e:
            self.logger.error(f"等待图像失败: {e}")
            return False

    def input_text(self, text_content: str) -> bool:
        """输入文本"""
        try:
            # Airtest中使用text()函数输入文本
            airtest_text(text_content)
            return True
        except Exception as e:
            self.logger.error(f"输入文本失败: {e}")
            return False

    def swipe_screen(
        self, start_x: int, start_y: int, end_x: int, end_y: int, duration: float = 0.5
    ) -> bool:
        """滑动屏幕"""
        try:
            swipe((start_x, start_y), (end_x, end_y), duration=duration)
            return True
        except Exception as e:
            self.logger.error(f"滑动失败: {e}")
            return False

    def press_key(self, key: str) -> bool:
        """按键操作"""
        try:
            keyevent(key)
            return True
        except Exception as e:
            self.logger.error(f"按键操作失败: {e}")
            return False

    def press_back(self) -> bool:
        """按返回键"""
        return self.press_key("BACK")

    def press_home(self) -> bool:
        """按Home键"""
        return self.press_key("HOME")

    def screenshot(self, filename: Optional[str] = None) -> str:
        """截图"""
        try:
            if filename is None:
                filename = f"screenshot_{int(time.time())}.png"

            snapshot(filename=filename)
            self.logger.info(f"截图已保存: {filename}")
            return filename

        except Exception as e:
            self.logger.error(f"截图失败: {e}")
            return ""

    def get_text_from_screen(self) -> str:
        """获取屏幕上的文本（需要OCR支持）"""
        try:
            # Airtest支持OCR文本识别，但需要额外配置
            # 这里提供基础框架，具体实现可以根据需要扩展
            return ""
        except Exception as e:
            self.logger.error(f"获取屏幕文本失败: {e}")
            return ""

    def find_and_click_fuzzy_text(self, text_pattern: str, timeout: int = 5) -> bool:
        """模糊匹配文本并点击"""
        try:
            # 截图然后进行文本识别和匹配
            screenshot_path = self.screenshot()

            # 这里可以集成OCR库进行文本识别
            # 暂时使用Airtest的基础文本匹配
            return self.click_text(text_pattern, timeout)

        except Exception as e:
            self.logger.error(f"模糊文本匹配点击失败: {e}")
            return False

    def scroll_to_find_text(self, text: str, max_scrolls: int = 5) -> bool:
        """滚动查找文本"""
        try:
            for i in range(max_scrolls):
                if self.wait_for_text(text, timeout=2):
                    return True
                # 向下滚动
                swipe((0.5, 0.8), (0.5, 0.2))
                sleep(1)

            return False
        except Exception as e:
            self.logger.error(f"滚动查找文本失败: {e}")
            return False

    def is_app_running(self, package_name: Optional[str] = None) -> bool:
        """检查App是否运行"""
        try:
            if package_name is None:
                package_name = self.config.get("mobile", {}).get(
                    "app_package", "cn.damai"
                )

            # 获取当前运行的应用
            if self.device and hasattr(self.device, "get_top_activity"):
                current_app = self.device.get_top_activity()
                if current_app:
                    return package_name in current_app.get("package", "")

            return False
        except Exception as e:
            self.logger.error(f"检查App运行状态失败: {e}")
            return False

    def close_device(self) -> None:
        """关闭设备连接"""
        try:
            self.logger.info("Airtest设备连接已关闭")
        except Exception as e:
            self.logger.error(f"关闭设备连接失败: {e}")


# 兼容性包装器
class MobileDriver(AirtestMobileDriver):
    """兼容性包装器，使其可以替代原来的驱动器"""

    def find_element(self, **kwargs) -> bool:
        """查找元素（兼容接口）"""
        if "text" in kwargs:
            return self.wait_for_text(kwargs["text"], timeout=2)
        elif "textContains" in kwargs:
            return self.wait_for_text(kwargs["textContains"], timeout=2)
        else:
            self.logger.warning(f"不支持的查找条件: {kwargs}")
            return False

    def click_element(self, timeout: int = 10, **kwargs) -> bool:
        """点击元素（兼容接口）"""
        if "text" in kwargs:
            return self.click_text(kwargs["text"], timeout)
        elif "textContains" in kwargs:
            return self.click_text(kwargs["textContains"], timeout)
        else:
            self.logger.warning(f"不支持的点击条件: {kwargs}")
            return False

    def wait_for_element(self, timeout: int = 10, **kwargs) -> bool:
        """等待元素出现（兼容接口）"""
        return self.find_element(**kwargs)

    def tap_coordinate(self, x: int, y: int) -> None:
        """点击坐标（兼容接口）"""
        self.click_coordinate(x, y)

    def get_text(self, **kwargs) -> str:
        """获取元素文本（兼容接口）"""
        return self.get_text_from_screen()

    def swipe(
        self, fx: float, fy: float, tx: float, ty: float, duration: float = 0.5
    ) -> None:
        """滑动操作（兼容接口）"""
        # 转换相对坐标为绝对坐标
        if self.device and hasattr(self.device, "get_display_info"):
            try:
                display = self.device.get_display_info()
                width, height = display.get("width", 1080), display.get("height", 1920)
            except:
                width, height = 1080, 1920  # 默认分辨率
        else:
            width, height = 1080, 1920  # 默认分辨率

        start_x = int(fx * width)
        start_y = int(fy * height)
        end_x = int(tx * width)
        end_y = int(ty * height)

        self.swipe_screen(start_x, start_y, end_x, end_y, duration)
